package com.casic.common.utils;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;

import java.util.NoSuchElementException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author Li
 * @create 2019-04-17 11:29
 * @descriptions FTPClient 连接池
 */
public class FTPClientPool implements ObjectPool<FTPClient> {

    private FTPClientFactory ftpClientFactory;

    /**
     * 连接池对象
     */
    private final BlockingQueue<FTPClient> pool;


    public FTPClientPool(FTPClientFactory ftpClientFactory, int maxSize) {
        this.ftpClientFactory = ftpClientFactory;
        pool = new ArrayBlockingQueue<>(maxSize);
        initPool(maxSize);
    }

    /**
     * 初始化连接池
     * @param maxPoolSize 最大连接数
     * @throws Exception
     */
    private void initPool(int maxPoolSize) {
        try {
            for(int i = 0; i < maxPoolSize; i++) {
                addObject();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从连接池获取一个连接
    @Override
    public FTPClient borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
        FTPClient ftpClient = pool.take();
        // 如果为空，重新获取建立连接
        if(ftpClient == null) {
            ftpClient = ftpClientFactory.makeObject();
        }
        // 如果验证连接失败，移除无效的客户端并重新获取建立连接
        if(!ftpClientFactory.validateObject(ftpClient)) {
            invalidateObject(ftpClient);
            ftpClient = ftpClientFactory.makeObject();
        }
        return ftpClient;
    }

    // 将一个连接放回连接池
    @Override
    public void returnObject(FTPClient ftpClient) throws Exception {
        if(ftpClient != null && !pool.offer(ftpClient, 3, TimeUnit.SECONDS)) {
            ftpClientFactory.destroyObject(ftpClient);
        }
    }

    @Override
    public void invalidateObject(FTPClient ftpClient) throws Exception {
        // 移除无效的客户端
        pool.remove(ftpClient);
        // 立即释放资源，避免冲突
        ftpClientFactory.destroyObject(ftpClient);
    }

    @Override
    public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
        // 插入对象的队列
        pool.offer(ftpClientFactory.makeObject(), 3, TimeUnit.SECONDS);
    }

    @Override
    public int getNumIdle() throws UnsupportedOperationException {
        return 0;
    }

    @Override
    public int getNumActive() throws UnsupportedOperationException {
        return 0;
    }

    @Override
    public void clear() throws Exception, UnsupportedOperationException {

    }

    // 关闭连接池
    @Override
    public void close() throws Exception {
        while(pool.iterator().hasNext()) {
            FTPClient ftpClient = pool.take();
            ftpClientFactory.destroyObject(ftpClient);
        }
    }

    @Override
    public void setFactory(PoolableObjectFactory<FTPClient> factory) throws IllegalStateException, UnsupportedOperationException {

    }

    public FTPClientFactory getFtpClientFactory() {
        return ftpClientFactory;
    }
}
